package com.yekaile.carsystem.advice;

import cn.hutool.core.date.DateUtil;
import com.yekaile.carsystem.common.Constant;
import com.yekaile.carsystem.entity.SystemLog;
import com.yekaile.carsystem.entity.User;
import com.yekaile.carsystem.mapper.SystemLogMapper;
import com.yekaile.carsystem.service.UserService;
import com.yekaile.carsystem.util.IPUtils;
import com.yekaile.carsystem.util.JwtUtil;
import com.yekaile.carsystem.util.RedisUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;

/**
 * aop，切面日志，这个类可以对在controller中的方法请求后输出请求参数
 * @author yekaile
 */
@Component
@Aspect
public class ControllerAspect {

    private final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);

    RedisUtil redisUtil;
    SystemLogMapper systemLogMapper;
    UserService userService;

    @Autowired
    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    @Autowired
    public void setSystemLogMapper(SystemLogMapper systemLogMapper) {
        this.systemLogMapper = systemLogMapper;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Pointcut("execution(* com.yekaile.carsystem.controller.*.*(..))")
    public void pointcut() {

    }

    @Before("pointcut()")
    public void printBefore(JoinPoint joinPoint) throws IOException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader(Constant.AUTHORIZATION_HEADER);
        String username;
        if (Constant.LOGIN_METHOD.equals(joinPoint.getSignature().getName())) {
            Object[] args = joinPoint.getArgs();
            User user = (User) args[0];
            username = user.getUsername();
        } else {
            username = JwtUtil.getClaim(token, Constant.USERNAME);
        }
        User user = userService.getUser(username);
        SystemLog log = new SystemLog();
        log.setGmtCreated(DateUtil.now());
        log.setIp(IPUtils.getIP(request));
        log.setUserId(user.getUserId());
        log.setUsername(user.getUsername());
        log.setRequestMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        log.setArgs(Arrays.toString(joinPoint.getArgs()));
        systemLogMapper.insertSelective(log);
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
        //获取所有参数方法一：
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String paraName = enu.nextElement();
            System.out.println(paraName + ": " + request.getParameter(paraName));

        }
    }

}
